grammar Dispatcher;

options {
  language = Java;
  output = AST;
}

tokens {METHODS; METHOD; DEF; SIGNATURE; TYPE;}

@header { package org.rx; }
@lexer::header { package org.rx; }

start: method_def+ -> ^(METHODS method_def+);

method_def	: t=TEMPLATENAME? n=NAME s=signature rtype  '{' (definition ';'?)* '}' ';'? 
			-> ^(METHOD[$n.text] rtype $s $t? definition*);

rtype
	: ':' t=NAME -> $t
	| -> TYPE["void"]
	;

signature: '(' (t+=NAME (',' t+=NAME)*)? ')' -> ^(SIGNATURE $t*);

definition
	: n=NAME '('  l=NAME ',' r=NAME ')'  -> ^(DEF[$n] $l $r)
	| m=MODIFIER -> $m
	;

MODIFIER : 
	('SWAP' |'TABLE' | 'SWITCH' | 'BTD' | 'INLINE' | 'swap' | 'table' | 'switch' | 'btd' | 'inline');

WS: ( SPACE
	| LINEBREAK
	) {$channel=HIDDEN;}
    ;

COMMENT	: '//' ~(LINEBREAK)* (LINEBREAK | EOF) {$channel=HIDDEN;} ;

fragment
SPACE
	: ' ' 
	| '\t'
	;

fragment
LINEBREAK
    : '\n'
    | '\r'
    | '\n\r'
    ;
  
fragment  
BASIC_NAME
    : WORD_NAME ('::' WORD_NAME)*
    ;
fragment
WORD_NAME
	: ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
	;
fragment
TNAME
	: (('struct' (SPACE+| (SPACE* '*' SPACE*)))? BASIC_NAME '*'?)
	;
TEMPLATENAME
	: 'template' SPACE* '<' SPACE* BASIC_NAME SPACE+ BASIC_NAME (SPACE* ',' SPACE* BASIC_NAME SPACE+ BASIC_NAME)* SPACE* '>'
	;
NAME
	: TNAME ('<' SPACE* TNAME (SPACE* ',' SPACE* TNAME)* SPACE* '>')?
	;